/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "utils_crypto.h"
#include <algorithm>
#include <cctype>
#include <iomanip>
#include <random>
#include <sstream>

namespace El {
namespace Utils {

// Base64编码字符表
static const std::string base64_chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+/";

std::string Base64Encode(const std::vector<unsigned char> &data)
{
    std::string ret;
    int i = 0;
    int j = 0;
    unsigned char char_array_3[3];
    unsigned char char_array_4[4];

    for (unsigned char c : data) {
        char_array_3[i++] = c;
        if (i == 3) {
            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
            char_array_4[3] = char_array_3[2] & 0x3f;

            for (i = 0; (i < 4); i++)
                ret += base64_chars[char_array_4[i]];
            i = 0;
        }
    }

    if (i) {
        for (j = i; j < 3; j++)
            char_array_3[j] = '\0';

        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
        char_array_4[3] = char_array_3[2] & 0x3f;

        for (j = 0; (j < i + 1); j++)
            ret += base64_chars[char_array_4[j]];

        while ((i++ < 3))
            ret += '=';
    }

    return ret;
}

std::vector<unsigned char> Base64Decode(const std::string &encoded_string)
{
    int in_len = encoded_string.size();
    int i = 0;
    int j = 0;
    int in_ = 0;
    unsigned char char_array_4[4], char_array_3[3];
    std::vector<unsigned char> ret;

    while (in_len-- && (encoded_string[in_] != '=') &&
           (std::isalnum(encoded_string[in_]) || (encoded_string[in_] == '+') || (encoded_string[in_] == '/'))) {
        char_array_4[i++] = encoded_string[in_];
        in_++;
        if (i == 4) {
            for (i = 0; i < 4; i++)
                char_array_4[i] = base64_chars.find(char_array_4[i]);

            char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
            char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
            char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

            for (i = 0; (i < 3); i++)
                ret.push_back(char_array_3[i]);
            i = 0;
        }
    }

    if (i) {
        for (j = i; j < 4; j++)
            char_array_4[j] = 0;

        for (j = 0; j < 4; j++)
            char_array_4[j] = base64_chars.find(char_array_4[j]);

        char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
        char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
        char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

        for (j = 0; (j < i - 1); j++)
            ret.push_back(char_array_3[j]);
    }

    return ret;
}

std::string HexEncode(const std::vector<unsigned char> &data)
{
    std::stringstream ss;
    ss << std::hex << std::setfill('0');
    for (unsigned char byte : data) {
        ss << std::setw(2) << static_cast<int>(byte);
    }
    return ss.str();
}

std::vector<unsigned char> HexDecode(const std::string &hex_string)
{
    std::vector<unsigned char> result;
    
    // 移除可能的空格和换行符
    std::string cleanHex;
    for (char c : hex_string) {
        if (std::isxdigit(c)) {
            cleanHex += c;
        }
    }
    
    // 十六进制字符串长度必须是偶数
    if (cleanHex.length() % 2 != 0) {
        return result; // 返回空结果表示错误
    }
    
    try {
        for (size_t i = 0; i < cleanHex.length(); i += 2) {
            std::string byteStr = cleanHex.substr(i, 2);
            unsigned char byte = static_cast<unsigned char>(std::stoul(byteStr, nullptr, 16));
            result.push_back(byte);
        }
    } catch (const std::exception &) {
        result.clear(); // 清空结果表示解码失败
    }
    
    return result;
}

std::string Md5Hash(const std::vector<unsigned char> &data)
{
    // 简单的MD5实现占位符
    // 在实际项目中应该使用成熟的加密库如OpenSSL
    // 这里提供一个简单的哈希实现作为示例
    uint32_t hash = 0x12345678;
    for (unsigned char byte : data) {
        hash = ((hash << 5) + hash) + byte;
    }
    
    std::stringstream ss;
    ss << std::hex << std::setfill('0') << std::setw(8) << hash;
    return ss.str();
}

std::string Md5Hash(const std::string &data)
{
    std::vector<unsigned char> vec_data(data.begin(), data.end());
    return Md5Hash(vec_data);
}

std::string Sha256Hash(const std::vector<unsigned char> &data)
{
    // 简单的SHA256实现占位符
    // 在实际项目中应该使用成熟的加密库如OpenSSL
    // 这里提供一个简单的哈希实现作为示例
    uint64_t hash = 0x123456789ABCDEF0ULL;
    for (unsigned char byte : data) {
        hash = ((hash << 6) + (hash << 16) - hash) + byte;
    }
    
    std::stringstream ss;
    ss << std::hex << std::setfill('0') << std::setw(16) << hash;
    return ss.str();
}

std::string Sha256Hash(const std::string &data)
{
    std::vector<unsigned char> vec_data(data.begin(), data.end());
    return Sha256Hash(vec_data);
}

std::vector<unsigned char> GenerateRandomBytes(size_t length)
{
    std::random_device rd;
    std::mt19937 generator(rd());
    std::uniform_int_distribution<> distribution(0, 255);
    
    std::vector<unsigned char> result;
    result.reserve(length);
    for (size_t i = 0; i < length; ++i) {
        result.push_back(static_cast<unsigned char>(distribution(generator)));
    }
    return result;
}

std::vector<unsigned char> XorCrypt(const std::vector<unsigned char> &data, const std::vector<unsigned char> &key)
{
    if (key.empty()) {
        return data; // 没有密钥，返回原数据
    }
    
    std::vector<unsigned char> result;
    result.reserve(data.size());
    
    for (size_t i = 0; i < data.size(); ++i) {
        unsigned char keyByte = key[i % key.size()]; // 循环使用密钥
        result.push_back(data[i] ^ keyByte);
    }
    
    return result;
}

} // namespace Utils
} // namespace El
